/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bff.core.action.query;

import com.inspur.edp.bef.auditconfig.entity.BefAuditConfigItem;
import com.inspur.edp.bff.api.manager.IFSManagerContext;
import com.inspur.edp.cef.api.ValueGetterConfig;
import com.inspur.edp.cef.core.valuegetter.CefValueGetter;
import com.inspur.edp.cef.entity.entity.IEntityData;
import io.iec.edp.caf.audit.api.data.GspAudit;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;

public class AuditUtils {
    public static Map<String, List<String>> getAuditMessageField(GspAudit gspAudit,
                                                                 BefAuditConfigItem item, Map<String, List<String>> auditMessageDataFields, Map<String, Map<String, List<String>>> childAuditMessageDataFields) {
        Stack stack = new Stack();
        Map<String, List<String>> fields = new HashMap<>();
        Map<String, Map<String, List<String>>> childFields = new HashMap<>();
        if (item.getAuditMessage() == null || item.getAuditMessage().getAuditMessage() == null || !item.getAuditMessage().getAuditMessage().contains("#")) {
            return fields;
        }
        String[] list = item.getAuditMessage().getAuditMessage().split("#");
        for (int i = 0; i < list.length; i++) {
            if (stack.isEmpty()) {
                stack.push(0);
                continue;
            }
            if (list[i].contains("data:")) {
                if (list[i].indexOf("/") < 0) {
                    fields.put(list[i].replaceFirst("data:", ""), new ArrayList<>());
                } else {
                    String prefix = list[i].substring(0, list[i].lastIndexOf("/")).replaceFirst("data:", "");
                    if (childFields.containsKey(prefix) == false)
                        childFields.put(prefix, new HashMap<>());
                    childFields.get(prefix).put(list[i].replaceFirst("data:" + prefix + "/", ""), new ArrayList<>());
                }
                stack.pop();
            }
        }
        auditMessageDataFields.putAll(fields);
        childAuditMessageDataFields.putAll(childFields);
        return fields;
    }

    public static void addAuditMessageFieldValue(IEntityData data, String entityCode, Map<String, List<String>> auditMessageDataFields,
                                                 Map<String, Map<String, List<String>>> childAuditMessageDataFields, IFSManagerContext managerContext) {

        setCurrentDataValue(data, auditMessageDataFields, entityCode, managerContext);

        for (Map.Entry<String, Map<String, List<String>>> childFields : childAuditMessageDataFields.entrySet()) {
            addAuditMessageChildFieldsValue(childFields, data, managerContext);
        }
    }

    private static void setCurrentDataValue(IEntityData data, Map<String, List<String>> fields, String entityCode, IFSManagerContext managerContext) {
        if (fields == null || fields.size() == 0)
            return;
        for (Entry<String, List<String>> entry : fields.entrySet()) {

            entry.getValue().add(getEntityDataFieldValue(data, entityCode, entry.getKey(), managerContext));
//      String.valueOf(
//          new CefValueGetter().getValue(data, entry.getKey(), new ValueGetterConfig())));
        }
    }

    private static void addAuditMessageChildFieldsValue(Entry<String, Map<String, List<String>>> childFields, IEntityData data, IFSManagerContext managerContext) {
        String[] childs = childFields.getKey().split("/");
        if (childs == null || childs.length == 0)
            return;
        List<IEntityData> parentDatas = new ArrayList<>();
        parentDatas.add(data);
        int index = 0;
        List<IEntityData> childDatas = addItems(index, childs, parentDatas);
        if (childDatas == null || childDatas.size() == 0)
            return;
        for (IEntityData item : childDatas) {
            setCurrentDataValue(item, childFields.getValue(), childs[childs.length - 1], managerContext);
        }
    }

    private static List<IEntityData> addItems(int index, String[] childs, List<IEntityData> parentDatas) {
        if (parentDatas == null || parentDatas.size() == 0)
            return null;

        List<IEntityData> childDatas = new ArrayList<>();
        for (IEntityData item : parentDatas) {
            if (item.getChilds() == null || item.getChilds().containsKey(childs[index]) == false)
                return null;
            childDatas.addAll(item.getChilds().get(childs[index]));
        }
        if (index == childs.length - 1)
            return childDatas;
        return addItems(index + 1, childs, childDatas);
    }

    static String getEntityDataFieldValue(IEntityData data, String entityCode, String fieldLabel,
                                          IFSManagerContext managerContext) {
        if (entityCode == null || entityCode.equals(""))
            entityCode = "RootNode";
        Object value = new CefValueGetter().getValue(data, fieldLabel, new ValueGetterConfig());
        if (value == null)
            return "";
        if (value instanceof Enum) {
            return managerContext.getBffManager().getModelInfo().getCustomResource(entityCode).getEnumPropertyDispalyValue(fieldLabel, String.valueOf(value));
        }
        if (value instanceof Date) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
            return sdf.format((Date) value);
        }
        return String.valueOf(value);
    }

    public static void setAuditMessage(GspAudit gspAudit, Map<String, List<String>> auditMessageDataFields, Map<String, Map<String, List<String>>> childAuditMessageDataFields) {

        for (Map.Entry<String, List<String>> entry : auditMessageDataFields.entrySet()) {
            String message = getFieldValue(entry.getValue());
            gspAudit.setDescription(
                    gspAudit.getDescription().replaceAll("#data:" + entry.getKey() + "#", message));
        }
        for (Map.Entry<String, Map<String, List<String>>> entry : childAuditMessageDataFields.entrySet()) {
            for (Entry<String, List<String>> childEntry : entry.getValue().entrySet()) {
                String message = getFieldValue(childEntry.getValue());
                if (message == null)
                    message = "";
                gspAudit.setDescription(gspAudit.getDescription().replaceAll("#data:" + entry.getKey() + "/" + childEntry.getKey() + "#", message));
            }
        }
    }

    private static String getFieldValue(List<String> value) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < value.size(); i++) {
            stringBuilder.append(value.get(i));
            if (i != value.size() - 1)
                stringBuilder.append(",");
        }
        return stringBuilder.toString();
    }
}
